package com.example.utils;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhy
 * @version 1.0.0
 * @ClassName VideoUtils.java
 * @Description TODO
 * @createTime 2021年06月18日 11:09:00
 */
public class VideoUtils {

	private static final Logger logger = LoggerFactory.getLogger(VideoUtils.class);

	/**
	 * 获取指定视频的帧并保存为图片至指定目录
	 *
	 * @param videoFile  源视频文件
	 * @param targetFileName 截取帧的图片全路径名字
	 * @throws Exception
	 */
	public static Map<String, Object> fetchFrame(File videoFile, String targetFileName) throws Exception {
		FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
		ff.start();
		int length = ff.getLengthInFrames();
		int i = 0;
		Frame f = null;
		while (i < length) {
			// 过滤前5帧，避免出现全黑的图片，依自己情况而定
			f = ff.grabFrame();
			if ((i > 5) && (f.image != null)) {
				break;
			}
			i++;
		}
		int owidth = f.imageWidth;
		int oheight = f.imageHeight;

		// 对截取的帧进行等比例缩放
//		int width = 800;
//		int height = (int) (((double) width / owidth) * oheight);

		Java2DFrameConverter converter = new Java2DFrameConverter();
		BufferedImage fecthedImage = converter.getBufferedImage(f);

//		BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
//		bi.getGraphics().drawImage(fecthedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
//		ff.flush();
//		ImageIO.write(bi, "jpg", resultFile);

		File resultFile = new File(targetFileName);
		ff.stop();
		ImageIO.write(fecthedImage, "jpg", resultFile);
		Map<String, Object> result = new HashMap<>();
		result.put("width", owidth);
		result.put("height", oheight);
		result.put("imgFile", resultFile);
		return result;
	}

	/**
	 * @param videoFile
	 * @return Map
	 */
	public static void getVideoMsg(File videoFile) {
//		Encoder encoder = new Encoder();
		FileChannel fc = null;
		ByteArrayOutputStream os = null;
		InputStream inputStream = null;
		FileInputStream fis = null;
		try {
//			MultimediaInfo m = encoder.getInfo(videoFile);
//			System.out.println("width=" + m.getVideo().getSize().getWidth());
//			System.out.println("height=" + m.getVideo().getSize().getHeight());

			fis = new FileInputStream(videoFile);
			fc = fis.getChannel();
			//截图准备
			FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(videoFile);
			grabber.start();
			//设置视频截取帧（默认取第一帧）
			Frame frame = grabber.grabImage();
			Java2DFrameConverter converter = new Java2DFrameConverter();
			//绘制图片
			BufferedImage bi = converter.getBufferedImage(frame);
			System.out.println("width=" + bi.getWidth() + "height=" + bi.getHeight());
			//创建文件
			File output = new File("/Users/zhanghaiyang/Desktop/temp.jpg");
			os = new ByteArrayOutputStream();
			ImageIO.write(bi, "jpg", os);
			inputStream = new ByteArrayInputStream(os.toByteArray());
			inputStreamToFile(inputStream, output);
			grabber.stop();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != fc) {
				try {
					fc.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void inputStreamToFile(InputStream ins, File file) {
		try {
			OutputStream os = new FileOutputStream(file);
			int bytesRead = 0;
			byte[] buffer = new byte[100 * 1024 * 1024];
			while ((bytesRead = ins.read(buffer, 0, 100 * 1024 * 1024)) != -1) {
				os.write(buffer, 0, bytesRead);
			}
			os.close();
			ins.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 下载视频
	 * @param urlPath 视频Url
	 * @param targetDirectory 要保存到的目录
	 * @return 视频文件
	 * @throws Exception
	 */
	public static File downloadVideoByUrl(String urlPath, String targetDirectory) throws Exception {
		System.out.println("url:" + urlPath);
		logger.info("url={}", urlPath);
		URL url = new URL(urlPath);
		HttpURLConnection http = (HttpURLConnection) url.openConnection();
		http.setConnectTimeout(3000);
		// 设置 User-Agent 避免被拦截
		http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
		String contentType = http.getContentType();
		System.out.println("contentType: " + contentType);
		// 获取文件大小
		long length = http.getContentLengthLong();
		System.out.println("文件大小：" + (length / 1024) + "KB");
		// 获取文件名
		String fileName = getFileName(http, urlPath);
		InputStream inputStream = http.getInputStream();
		byte[] buff = new byte[1024 * 10];
		File downloadFile = new File(targetDirectory, fileName);
		OutputStream out = new FileOutputStream(downloadFile);
		int len;
		int count = 0;// 计数
		while ((len = inputStream.read(buff)) != -1) {
			out.write(buff, 0, len);
			out.flush();
			++count;
		}
		System.out.println("count:" + count);
		// 关闭资源
		out.close();
		inputStream.close();
		http.disconnect();
		return downloadFile;
	}

	public static String getFileName(HttpURLConnection http, String urlPath) throws UnsupportedEncodingException {
		String headerField = http.getHeaderField("Content-Disposition");
		String fileName = null;
		if (null != headerField) {
			String decode = URLDecoder.decode(headerField, "UTF-8");
			fileName = decode.split(";")[1].split("=")[1].replaceAll("\"", "");
			System.out.println("文件名是： " + fileName);
			logger.info("file name={}", fileName);
		}
		if (null == fileName) {
			// 尝试从url中获取文件名
			String[] arr = urlPath.split("/");
			fileName = arr[arr.length - 1];
			System.out.println("url中获取文件名：" + fileName);
			logger.info("file name={}", fileName);
		}
		return fileName;
	}
}
